package net.gdface.utils;

import java.lang.ref.WeakReference;

import com.google.common.base.Function;
import com.google.common.base.Supplier;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * {@link Supplier}弱引用实现,当弱引用失效时重新执行加载
 * @author guyadong
 *
 * @param <T>
 * @since 2.9.3
 */
public class WeakSupplier<T> implements Supplier<T> {
	private final  Supplier<T> supplier;
	private volatile WeakReference<T> weakReference;

	/**
	 * @param supplier
	 * @param immediateLoading 是否立即加载，为{@code true}立即调用 supplier
	 */
	public WeakSupplier(Supplier<T> supplier, boolean immediateLoading) {
		this.supplier = checkNotNull(supplier,"supplier is null");
		if(immediateLoading) {
			doGet();
		}
	}

	public WeakSupplier(Supplier<T> supplier) {
		this(supplier, true);
	}

	private void doGet() {
		weakReference = new WeakReference<>(checkNotNull(supplier.get(),"value from supplier %s is null",supplier));
	}
	@Override
	public T get() {
		if(null == weakReference) {
			synchronized (this) {
				if(null == weakReference) {
					doGet();
				}
			}
		}
		if(null == weakReference.get()){
			/** 弱引用失效时，重新加载 */
//			System.out.println("reload");
			doGet();
		}
		return weakReference.get();
	}

	/**
	 * 创建{@link WeakSupplier}实例
	 * @param <T>
	 * @param supplier
	 * @param immediateLoading 是否立即加载，为{@code true}立即调用 supplier
	 */
	public static <T> WeakSupplier<T> of(Supplier<T> supplier,boolean immediateLoading){
		if(supplier instanceof WeakSupplier) {
			return (WeakSupplier<T>) supplier;
		}
		return new WeakSupplier<>(supplier, immediateLoading);
	}
	/**
	 * 创建{@link WeakSupplier}实例(立即加载)
	 * @param <T>
	 * @param supplier
	 */
	public static <T> WeakSupplier<T> of(Supplier<T> supplier){
		return of(supplier,true);
	}
	public static<T>  Function<Supplier<T>, WeakSupplier<T>> weakSupplierFun(){
		return new Function<Supplier<T>, WeakSupplier<T>>(){
			@Override
			public WeakSupplier<T> apply(Supplier<T> input) {
				return of(input);
			}};
	}
}
